/**
 * 房间游戏数据模型
 * 
 * @author LuoDong
 * @email luo4521@online.net.tw
 * 2010-2-7 9:26
 */
package com.addcn.texas.model
{		
	import com.addcn.texas.data.GameUser;
	import it.gotoandplay.smartfoxserver.SmartFoxClient;
	import it.gotoandplay.smartfoxserver.SFSEvent;
	
	import com.addcn.fog.model.Model;	
	import com.addcn.fog.model.ModelLocator;	
		
	import com.addcn.texas.inter.IUser;
	import com.addcn.common.utils.Server;
	import com.addcn.texas.data.RoomUsers;
	import com.addcn.texas.utils.DataResolve;
	import com.addcn.texas.data.*;
	
	public class GameInfoModel extends Model
	{
		public static const GAME_DATA_REDY : String = "gameDataRedy";
		public static const GAME_START : String = "gameStart";
		public static const DEAL_COMMUNITY_CARDS : String = "dealCommunityCards";
		public static const DEAL_USER_POKER : String = "dealUserPoker";
		public static const SET_BANKER : String = "setBanker";
		public static const NEXT_PLAYER_CALL : String = "nextPlayerCall";
		public static const USER_STATUS_MSG : String = "userStatusMsg";
		public static const USER_BET : String = "userBet";
		public static const LOSE_PLAYER : String = "losePlayer";
		public static const GAME_OVER : String = "gameOver";		
		public static const POOL_LIST : String = "poolList";		 
		
		public static const GAME_WIN_RESULT : String = "gameWinResult";
		public static const REMAIN_PLAYER : String = "remainPlayer";
						
		private var _server : SmartFoxClient;
		private var _room_user : RoomUsers;   //房间中所有玩家对象
		private var _user_model : RoomUserModel;  
		private var _room_model : RoomModel; //房间数据模型引用		
		private var _dataResolve : DataResolve;	//数据解析对象
		private var _banker_sit : int;   //當前莊家位置
		private var _rule : Object;     //贏牌類型
		private var _public_poker : Array;  //公共牌
		private var _now_call : int;   //当前叫牌玩家ID	
		private var _game_pot : Array; //池底数据 
		private var _my_id : int;  //玩家自己的ID
		private var _winers : Object; //赢家信息，私有扑克牌，成手牌，赢牌类型
		private var _winers_chip : Array;
		
		private var _pot_winer : Array;
		
		
		//----------------------------------
		private var _game_data : Object;    //游戲數據		
		private var _pool: Array;		
		private var _limp_chip : int;   //本轮跟注所需筹码
		private var _before_chip : int;  //自己已经下注码
		private var _game_status : Boolean;
		//---------------------------------
		
		public function GameInfoModel() : void
		{			
			_initialize();
		}
		
		private function _initialize() : void
		{
			this._server = Server.getInstance();
			this._room_user = RoomUsers.getInstance(); 
			this._user_model = ModelLocator.getInstance().getModel(RoomUserModel);			
			this._room_model = ModelLocator.getInstance().getModel(RoomModel);			
			this._dataResolve = DataResolve.getInstance();
			this._rule = {
						FLUSH_WAY: 		"同花顺",
						FOUR_OF_A_KIND: "四条",
						FULL_HOUSE: 	"葫芦",
						FLUSH: 			"同花",
						WAY: 			"顺子",
						THREE_OF_A_KIND:"三条",
						TWO_TWAIN: 		"两对",
						TWAIN:			"一对",
						OFFSUIT: 		"高牌"
			};
			this._server.addEventListener(SFSEvent.onExtensionResponse, _responseHandler);
			_resetData();			
			var _model : UserInfoModel = ModelLocator.getInstance().getModel(UserInfoModel);
			//var _my_data : Object = _model.getUserInfo();  //獲取玩家自己的數據	
			//this._my_id = int(_my_data["id"]);  		//获取玩家自己的id	
			this._my_id = MyUser.getInstance().id;
			
			//---------------------------------
			this._game_data = { };
			this._game_data["pubPoker"] = [];   //公共牌
			this._game_data["myCards"] = [];  //玩家自己持有牌
			this._game_data["others"] = [];   //其他玩家私有牌
			this._game_data["call"] = 0;     //當前下注玩家座位號
			this._game_status = false;
			//----------------------------------		
						
		}
		
		/**
		 * 清空游戏数据
		 */
		private function _resetData() : void
		{
			this._public_poker = [];	//清空公共牌
			this._room_user.clearUserBet();  //清除玩家下注数据
			this._room_user.clearPoker(); //清除玩家扑克
			this._game_pot = [];  //清空池底
		}
		
		public function setGameData(r_data : Object) : void
		{
			var _data : Object = this._dataResolve._resolveGameInfo(r_data);
			//公共牌
			if(_data["publicPoker"] != null){
				_public_poker = _data["public"]
			}
			//当前叫牌
			if (_data["call"] != null) {
				_now_call = _data["call"];
			}
			//设置庄家
			if (_data["banker"] != null) {
				this._setBanker(_data["banker"]);
			}
			
			if(_public_poker.length > 0){
				sendNotification (DEAL_COMMUNITY_CARDS, _public_poker);  //發送通知,傳遞公共牌數據
			}			
		}
		
		private function _responseHandler(evt : SFSEvent) : void
		{
			var _data = evt.params.dataObj.dataObj;		
			switch(evt.params.dataObj._cmd) {
				case "gameInfo":					
					_resetData(); //重置数据				    
					sendNotification(GAME_START);  //发送通知，游戏开始
					_setBanker(_data["banker"]);  //设置庄家
				//	_setBlinds(_data);	//下大小盲注
					break;
				case "comCards":			
					_room_user.clearUserBet();
					_communityCards(_data.poker); //发公共牌				 				
					break;
				case "deal":										
					_dealPoker(_data);
					break;
				case "bet":
					_userBetHandler(_data);	
					break;
				case "next":					
					_nowCallPlayer(_data);	
					break;				
				case "allotPot":		
					this._game_status = false;
					_gameOver(_data as Array);				
					break;
				case "potList":  //池底列表					
					MonsterDebugger.trace("potList", _data);
					//生成池底
					var _pot : Array = _data.pot;
					_createPot(_pot);	
					//sendNotification(POOL_LIST, _data);
					break;
				case "onegamer":
					_remainPlayer(_data);									
					break;	
					
					
				case "action":				
					trace("----------------->" + this._my_id + "   "+_data["uid"])
					if (this._my_id == _data["uid"]) {
						
						var _param = { };
						//_data["chip"] = 4;
						_param["type"] = 2;
						//_server.sendXtMessage(Server.ext(0), "gameAc", _param, SmartFoxClient.XTMSG_TYPE_JSON);	
					}
					break;
			}
		}
		
		/**
		 * 下注
		 * @param	r_data Object {way:int,chip:int},way:下注方式,0跟注,1加注,2棄牌,3全下,4看牌;
		 * 			bet:下注金額;
		 */
		public function bet(r_data : Object) : void
		{			
			var _way : int = r_data["way"];
			var _chip :int = r_data["chip"];			
			if (_way == 2 || _way == 4) {				
				_chip = 0;				
			}else if(_way != 5) {
				var _user : GameUser = _room_user.getUser(this._my_id);				
				if (_chip > _room_user.userMaxBet()) {					
					_way = 1;
				}else if(_chip == _room_user.userMaxBet()){					
					if (_chip == (_user.chip + _user.bet)) {
						_way = 3;
					}else {
						_way = 0;
					}
				}
				_chip = _chip - _user.bet;
			}
			var _data : Object = { };			
			_data["ac"] = "bet";
			_data["way"] = _way;
			_data["chip"] = _chip;			
			_server.sendXtMessage(Server.ext(0), "pokerAc", _data, SmartFoxClient.XTMSG_TYPE_JSON);								
		}
		
		private function  _analyseBet(r_bet : int) : void
		{

		}
				
		/**
		 * 解析扑克牌
		 * @param	r_data  Object 
		 * @return	Array   [ [牌型,花色],[牌型,花色],... ], 牌型范围为A-K, 花色范围为0-3，0为黑桃，1为红桃，2为梅花，3为方片
		 */
		private function _resolvePoker(r_data : Object) : Array
		{	
			var _arr : Array = [];
			var _cards : Array = [];
			var _val : String;
			for each(_val in r_data) {				
				_arr =  _val.split(",");
				_cards.push(_arr);				
			}
			return _cards;
		}
		
		/**
		 * 设置庄家ID
		 * @param	r_uid int
		 */
		private function _setBanker(r_uid: int) : void
		{
			var _user : GameUser = _room_user.getUser(r_uid);
			if (!_user) return;			
			var _sit : int = _user.sit;
			if (_sit == 0 || _sit > 9) return;
			this._banker_sit = _sit;						
			sendNotification(SET_BANKER, { sit: this._banker_sit } );			
		}
		
		/**
		 * 下大小盲注
		 * @param	r_data Object {max:int,min;int} max:大盲注玩家ID, min:小盲注玩家ID
		 */
		private function _setBlinds(r_data : Object) : void
		{
			var _max_id : int = r_data["max"];
			var _min_id : int = r_data["min"];			
			var _max_blind : int = this._room_model.getMaxBinld();
			var _min_blind : int = this._room_model.getMinBinld();
			var _max_user : GameUser = _room_user.getUser(_max_id);
			var _min_user : GameUser = _room_user.getUser(_min_id);			
			if (this._my_id == _max_id) {
				bet( { chip:_max_blind , way:5 } );
			}else if(this._my_id == _min_id){			
				bet( { chip:_min_blind , way:5 } );
			}	
		}
		
		/**
		 * 處理服務端返回的玩家下注數據
		 * @param	r_data Object {uid:int, way:int, chip:int}
		 */		
		private function _userBetHandler(r_data : Object) : void
		{			
			if ("err" in  r_data) return;			
			var _uid : int = r_data["uid"];
			var _bet : int = r_data["chip"];						
			var _bank : int = r_data["bank"] ; //剩余筹码
			var _user : GameUser = _room_user.getUser(_uid);		
			var _model : RoomUserModel = ModelLocator.getInstance().getModel(RoomUserModel);
			_model.modifyUserChip(_uid, _bank); //修改玩家筹码
			_user.bet = _user.bet +_bet;  //记录玩家当前下注筹码
			var _str : String = this._dataResolve.resolveCall(r_data["way"]); //解析叫牌方式		
			sendNotification(USER_STATUS_MSG, { sit:_user.sit, msg:_str } );   //发送叫牌方式通知
			if(_bet >0 ){ //玩家有下注
				sendNotification(USER_BET, { sit:_user.sit, bet : _user.bet } );  //发送下注筹码
			}
		}
		
		/**
		 * 當前叫牌玩家
		 * @param	r_data Object
		 */
		private function _nowCallPlayer(r_data : Object) : void
		{								
			var _uid : int = r_data["uid"];				
			var _sit : int = _room_user.getUserSit(_uid);
			var _user : GameUser = _room_user.getUser(_uid);
			if(_sit >0){						
				var _data : Object = { };
				if (this._my_id == _uid) {
					var _other : int = _room_user.userMaxChip();	//其他玩家最大筹码		
					var _chip : int = _user.chip + _user.bet;  //玩家剩余筹码 + 本輪已經下注籌碼							
					var _limp : int = _room_user.userMaxBet();  //本轮跟注到
					var _min : int = _limp > this._room_model.getMaxBinld() ? _limp : this._room_model.getMaxBinld();  //加注最小限制
					var _max : int = _chip > _other ? _other : _chip; // 加注最大限制
					_data["chip"] = _chip;
					_data["limp"] = _limp;
					_data["min"] = _min;
					_data["max"] = _max;					
					_data["show"] = true;					
				}				
				_data["sit"] = _sit;
				sendNotification(NEXT_PLAYER_CALL, _data);
			}
		}
		
		/**
		 * 整理池底数据
		 * @param	r_data  [int,int,...]
		 */
		private function  _createPot(r_data : Array) : void
		{						
			//this._game_pot = r_data;
			//sendNotification(POOL_LIST, this._game_pot); 	//发送通知，[int,int, ...]		
			//檢查池底是否有更改,有更改則發送通知
			for (var k in r_data) {
				if (this._game_pot[k] != r_data[k]) {
					this._game_pot = r_data;
					sendNotification(POOL_LIST, this._game_pot); 	//发送池底数据，[int,int, ...]
					break;
				}
			}	
			var _max_bet : int = _room_user.userMaxBet();  
			if (_max_bet > 0 ) {
				_room_user.clearUserBet();  //清除玩家本轮下注
			}			
		}
		
		/**
		 * 游戲結束
		 * @param	r_data Array 
		 */
		private function _gameOver(r_data : Array) : void
		{	
			var _win_data : Object = r_data[2];
			_winers = { };  //贏家信息
			var _uid : int;
			var _sit : int;
			for each(var val in _win_data) {			
				_uid = val["uid"];
				_sit = _room_user.getUserSit(_uid);
				_winers[_sit] = { };				
				_winers[_sit]["uid"] = _uid;
				_winers[_sit]["shape"] = _rule[val["winT"]];  //赢牌类型
				_winers[_sit]["poker"] = _resolvePoker(val["userP"]); //私有牌
				_winers[_sit]["hand"] = _resolvePoker(val["winP"]);  //成手牌
			}
			sendNotification(GAME_WIN_RESULT, _winers);  //发送通知，每个赢家的私有扑克牌、成手牌
						
			var _id_list : Array = r_data[1];
			var _obj : Object;				
			var _single : int;
			var _len : int;
			_winers_chip = [];
			for (var k in this._game_pot) {
				_len = _id_list[k].length;
				if (_len > 1) {
					_single = (_game_pot[k] / _len) >> 0;
				}else {
					_single = _game_pot[k];
				}
				_winers_chip[k] = [];
				for (var j in _id_list[k]) {					
					_obj = { };
					_obj["uid"] = _id_list[k][j];
					_obj["sit"] = _room_user.getUserSit(_obj["uid"]);
					_obj["chip"] = _single;
					if (j == 0) {
						var _rem  = _game_pot[k] % _len;
						if ( _rem != 0) {
							_obj["chip"] += _rem;
						}
					}
					_winers_chip[k][j] = _obj;
				}
				
			}
			sendNotification(GAME_OVER,_winers_chip);  //发送游戏结束通知
			_createPot(r_data[0]);	//更新池底										
		}
		
		public function _updateChip(r_index : int) : void
		{
			var _res : Array = _winers_chip[r_index];
			var _uid : int ;
			var _user : GameUser ;
			var _chip : int;
			for each(var v in _res) {				
				_uid = v["uid"];
				_user =  _room_user.getUser(_uid);
				_chip = _user.chip + v["chip"];
				_user_model.modifyUserChip(_uid,_chip);
			}
		}

		/**
		 * 玩家退出或棄牌,游戲結束
		 * @param	r_data  Object 
		 */
		private function _losePlayer(r_data : Object) : void
		{
			
			
			//var _uid : int = r_data["uid"];
			//var _sit : int = this._userSit(_uid);
			//var _chip : int = r_data["chip"] + this._user_model.getUserChip(_uid);					
			//this._user_model.modifyUserChip(_uid, _chip);
			//var _result : Object = {};
			//_result[0] = { type:"", sit:_sit, uid:_uid, userPoker:[], winPoker:[], chip:_chip };	
			//						
			//sendNotification(LOSE_PLAYER, _result[0]);
		}
				
		/**
		 * 发公共牌
		 * 
		 */
		private function _communityCards(r_data : Object) : void
		{
			if (this._public_poker.length >= 5) return;			
			var _cards : Array = _resolvePoker(r_data); //解析扑克牌
			this._public_poker = this._public_poker.concat(_cards); //保存到公共牌列表			
			sendNotification(DEAL_COMMUNITY_CARDS, _cards);  //发送通知			
		}

		/**
		 * 发玩家私有牌
		 * @param	r_data  {uid:int,poker:["牌型,花色", "牌型,花色"]}
		 */
		private function _dealPoker(r_data : Object) : void
		{				
			//根据ID设置玩家扑克
			var _uid = r_data["uid"]; 			
			var _poker : Array = _resolvePoker(r_data["poker"]);
			var _user : GameUser = this._room_user.getUser(_uid);			
			_user.poker = _poker;
			//获取所有坐下的玩家			
			var _sit_user : Object = this._room_user.getSitUsers();			
			var _sit_arr : Array = [];						
			for (var _k in  _sit_user) {
				_sit_arr.push(_k);
			}				
			//更改發牌順序,從莊家的后一位开始發牌,莊家為最后一位
			var _index = _sit_arr.indexOf(this._banker_sit);
			if (_index > -1 ) {
				var _tmp : Array = _sit_arr.splice(_index + 1);
				_sit_arr = _tmp.concat(_sit_arr);
			}
			sendNotification(DEAL_USER_POKER, { sit:_user.sit, poker: _poker, sitList:_sit_arr } );					
		}
			
		/**
		 * 剩余玩家，游戏中其他玩家弃牌或退出
		 * @param	r_data Object {uid:int, chip:int} uid:玩家id，chip:玩家当前所有筹码
		 */
		private function _remainPlayer(r_data : Object) : void
		{			
			_winers_chip = [];			
			var _uid : int = r_data["uid"];
			var _user :GameUser = _room_user.getUser(_uid);
			var _sit : int = _user.sit;
			var _chip : int = r_data["chip"];			
			_winers_chip[0] = [ { uid:_uid, sit:_sit, chip:_chip } ];
			sendNotification(REMAIN_PLAYER, _winers_chip);			
		}
			
		override public function destroy():void 
		{
			this._game_data = null;
			_server.removeEventListener(SFSEvent.onExtensionResponse, _responseHandler);
		}
	}
	
}
